#ifndef DOMAIN_H
#define DOMAIN_H

#include "Point.h"

template<unsigned int DIM>
class Domain
{
public:

    /**
     * @brief Construct a new Domain object
     */
    Domain();

    /**
     * @brief Construct a new Domain object by vector<Point<DIM> > in std namespace;
     *        利用({{0,0},{1,0},{1,1},{0,1}})可以进行初始化；
     */
    Domain(const int num);

    /**
     * @brief Destroy the Domain object
     */
    ~Domain();

    /**
     * @brief 重载下标运算符operator[]
     * @param r 指定第几个几何点；
     * @return Point<DIM>& 几何点引用；
     */
    Point<DIM>& operator[](int r){return _Pointlist[r];};

protected:
    std::vector<Point<DIM> > _Pointlist;
};



template<unsigned int DIM>
Domain<DIM>::Domain()
{    
};

template<unsigned int DIM>
Domain<DIM>::Domain(const int num)
{
    _Pointlist.resize(num);
};

template<unsigned int DIM>
Domain<DIM>::~Domain()
{
};


/**
 * @brief 矩形计算区域类
 * 
 */
class RectangleDomain:public Domain<2U>
{   
public:
    typedef Domain<2U> _base;
    using _base::_Pointlist;
public:
    /**
    * @brief 构造一个矩形区域,默认为[0,0]*[1,1];
    * 
    */
    RectangleDomain();
    /**
     * @brief 通过给定的四个点构造矩形区域
     * 
     */
    RectangleDomain(std::vector<Point<2>>);
    /**
     * @brief Destroy the Rectangle Domain object
     */
    ~RectangleDomain(){};
    /**
     * @brief 返回矩形区域的所有边界；
     * 
     * @return std::vector<Boundary<2>> 
     */
    std::vector<Boundary<2>> boundary();
     /**
     * @brief 重载下标运算符operator[]
     * @param r 指定第几个几何点；
     * @return Point<DIM>& 几何点引用；
     */
    Point<2U>& operator[](int r);

};

RectangleDomain::RectangleDomain()
{
    _Pointlist.resize(4);
    _Pointlist[0] = {0,0};
    _Pointlist[1] = {1,0};
    _Pointlist[2] = {1,1};
    _Pointlist[3] = {0,1};
};

RectangleDomain::RectangleDomain(std::vector<Point<2>> p) 
{
     _Pointlist = p;
};

std::vector<Boundary<2>> RectangleDomain::boundary()
{
    std::vector<Boundary<2>> temp;
    
    for(int i = 0;i < 3;i++)
    {
        std::vector<Point<2>> p;
        p.push_back(_Pointlist[i]);
        p.push_back(_Pointlist[i+1]);
        Boundary<2> b(p);
        temp.push_back(b);
    }
    std::vector<Point<2>> p4(2);
    p4[0] = _Pointlist[3];
    p4[1] = _Pointlist[0];
    temp.push_back(p4);
    return temp;
};

Point<2U>& RectangleDomain::operator[](int r)
{
    return _Pointlist[r];
};

#else
#endif /* DOMAIN_H */
